#!/usr/bin/env python

from sys import *
import cgi
import cgitb
cgitb.enable()

__version__ = "<b>0.1.0</b>/20100315";
__author__ = "towi@geocities.com";

CSS = ("""
body { font-family: sans-serif; }
div#divAll { border:1px solid %(bgMed)s }
#spnBridgy { color:#999; font-weight:bold; font-family:serif; font-style:italic; padding-left:2px; padding-right:2px; }
#spnVersion { font-size:0.5em; color:#999; font-family:serif; font-style:italic; display:none; }
table.tbl { width:100%%; }
td.hd { text-align:left; background:%(bgMed)s; font-size:0.9em; }
#txtBoardSet { font-size:0.6em; width:100%%; }
td.thName { width:100%%; background:%(bgMed)s; }
#spnDescr      { font-size: 0.6em; color:#666; }
#spnTitle      { font-size: 0.6em; color:#666; }
div.divName { font-size: 0.7em; }
tbl#tblGame tr td { border-bottom: 1px solid #ddd; }
div#divYourCards { border: 1px solid #ddd; }
span.btn { background:#eee; border:1px solid #aaa; font-size:0.7em;
           padding-top:2px; padding-bottom:2px; padding-left:8px; padding-right:8px;
           margin:1px; cursor:pointer; }
.en { cursor:pointer; color:black; }
.dis { cursor:auto; color:#ccc; display:none; }
#btnClear { right:0px; }
""") % {
    'bgMed' : '#c9e2fc' # bgColor medium dark (head and foot elements of google containers)
}

contentDivGameSelect = ("""
<table id=tblGameSelect class=tbl>
  <tr><td class=hd>boardset</td><td><input type=text id=txtBoardSet value='http://www.generisch.de/t/bridgyset.py' class='gwt-TextBox' size=30/></td>
  <tr><td class=hd>random</td>  <td>
           <span class=btn id=btnRandNs  onclick='randBoardId("ns")' alt='Board for practice N-S bidding'>N-S</span>
           <span class=btn id=btnRand4Pl onclick='randBoardId("4pl")' alt='Most random board'>4Players</span>
           </td></tr>
  <tr><td class=hd>boardid</td> <td>
           <input type=text  id=txtBoardId value='' size=10 class='gwt-TextBox'/>
           <span class=btn   id=btnSet  onclick='setBoardBySetAndId()'>set</span>
           </td></tr>
  <tr><td class=hd>descr.</td>   <td> <span id=spnDescr>...</span> </td></tr>
</table>
""")

contentDivGame = ("""
<table id=tblGame class=tbl>
  <tr><td></td><td>%(btnN)s</td><td></td><td class=thName>%(nameN)s</td></tr>
  <tr><td>%(btnW)s</td><td></td><td></td><td class=thName>%(nameW)s</td></tr>
  <tr><td></td><td></td><td>%(btnE)s</td><td class=thName>%(nameE)s</td></tr>
  <tr><td></td><td>%(btnS)s</td><td></td><td class=thName>%(nameS)s</td></tr>
  <tr><td colspan=4> <div id="divYourCards">.</div> </td></tr>
</table>
""") % {
    'btnN' : """<span class='btn en btnCompass' id=enCompassN onclick='compass("N")'>N</span><span class='btn dis btnCompass' id=disCompassN>N</span>""",
    'btnE' : """<span class='btn en btnCompass' id=enCompassE onclick='compass("E")'>E</span><span class='btn dis btnCompass' id=disCompassE>E</span>""",
    'btnS' : """<span class='btn en btnCompass' id=enCompassS onclick='compass("S")'>S</span><span class='btn dis btnCompass' id=disCompassS>S</span>""",
    'btnW' : """<span class='btn en btnCompass' id=enCompassW onclick='compass("W")'>W</span><span class='btn dis btnCompass' id=disCompassW>W</span>""",
    'nameN' : """<div id=divNameN class=divName>?</div>""",
    'nameE' : """<div id=divNameE class=divName>?</div>""",
    'nameS' : """<div id=divNameS class=divName>?</div>""",
    'nameW' : """<div id=divNameW class=divName>?</div>""",
}

DIV = ("""
    <style type="text/css">
      %(css)s
    </style>

    <script type="text/javascript">

    var BOARDS = new Array();  // json
    BOARDS[42] = ('{'
        +'title : "a junk board",'
        +'explainUrl: "",'
        +'boardSet: "-",'
        +'boardId: "42",'
        +'"N": "%(C)s345  %(D)s29BA  %(H)s0     %(S)s240DKA",'
        +'"E": "%(C)s27   %(D)sDK    %(H)s456DA %(S)s2354B",'
        +'"S": "%(C)s35K  %(D)s23B   %(H)s48    %(S)s68",'
        +'"W": "%(C)sDA   %(D)s23478 %(H)s0     %(S)s7",'
        +'}');
    BOARDS[23] = ('{'
        +'title : "another junk board",'
        +'explainUrl: "",'
        +'boardSet: "-",'
        +'boardId: "23",'
        +'"N": "%(C)s345  %(D)s29BA  %(H)s0     %(S)s240DKA",'
        +'"E": "%(C)s27   %(D)sDK    %(H)s456DA %(S)s2354B",'
        +'"S": "%(C)s35K  %(D)s23B   %(H)s48    %(S)s68",'
        +'"W": "%(C)sDA   %(D)s23478 %(H)s0     %(S)s7",'
        +'}');

    //
    // general helpers
    //

    function display(style, theid) { /* show or hide a display-group */
        var elem = document.getElementById(theid);
        elem.style.display = style;
    }

    function showVersion() {
        document.getElementById('spnBridgy').style.display = 'none';
        document.getElementById('spnVersion').style.display = 'inline';
    }
    function hideVersion() {
        document.getElementById('spnBridgy').style.display = 'inline';
        document.getElementById('spnVersion').style.display = 'none';
    }

    function clearBridgy() {
       var state = wave.getState();
       // 'boardSet' is left untouched.
       var info = { N:null, S:null, E:null, W:null,
         board:null, boardId:null, boardTitle:null
       }
       state.submitDelta(info);
    }

    //
    // game select functions
    //

    function response_id(obj) {
        alert(obj.text);
        var state = wave.getState();
        var info = { txtBoardId : obj.text }
        state.submitDelta(info);
    };
    function randBoardId(selectType) { // selectType: 'ns' or '4pl' or any other supported by boardset
        params = { gadgets.io.RequestParameters.METHOD: gadgets.io.MethodType.GET };
        var boardSet = document.getElementById('txtBoardSet').value;
        var url = boardSet + "?f=randid&s=" + selectType;
        gadgets.io.makeRequest(url, response_id, params);
        var state = wave.getState();
        var info = { txtBoardId : obj.text };
        if(boardSet != state.get("boardSet","")) info.boardSet = boardSet;
        state.submitDelta(info);
    }

    function response_board(obj) {
        alert(obj.text);
        var state = wave.getState();
        var boardId = document.getElementById('txtBoardId').value;
        var boardSet = document.getElementById('txtBoardSet').value;
        var info = { }
        if(boardId  != state.get("boardId", "")) info.boardId = boardId;
        if(boardSet != state.get("boardSet","")) info.boardSet = boardSet;
        info.board, obj.text;
        state.submitDelta(info);
    }
    function setBoardBySetAndId() {
        params = { gadgets.io.RequestParameters.METHOD: gadgets.io.MethodType.GET };
        var bid = document.getElementById('txtBoardId').value;
        var bset = document.getElementById('txtBoardSet').value;
        var url = bset + "?id="+bid+"&s=4pl"";
        gadgets.io.makeRequest(url, response_id, params);
    }

    //
    // main
    //

    function stateUpdated() {
        var me = wave.getViewer().getId();
        var state = wave.getState();
        //
        // which phase are we in? board already selected?
        var board = state.get("board", 0); /* { 'N': cards-as-html, ... } */
        display(board==0 ? "block" : "none", 'divGameSelect');
        display(board==0 ? "none" : "block", 'divGame');
        //
        // fill-in game select stuff
        document.getElementById('txtBoardId').value = state.get("boardId","");
        document.getElementById('spnDescr').innerHTML = state.get("boardDescription","");
        document.getElementById('spnTitle').innerHTML = state.get("boardTitle","");
        document.getElementById('txtBoardSet').value = state.get("boardSet","");
        //
        // fill-in board stuff.
        var divYourCards = document.getElementById('divYourCards');
        divYourCards.innerHTML = '<i style=color:#aaa;>Choose your seat</i>';
        var countMe = 0;
        eval("var eboard = " + board); // decode json
        for(var d in { N:'', E:'', S:'', W:'' } ) {
            var name = state.get(d, "?");
            if(name == me) {
                divYourCards.innerHTML = eboard[d];
                countMe += 1;
            }
            document.getElementById("divName"+d).innerHTML = name;
        }
        // disable buttons for choosing compass
        for(var d in { N:'', E:'', S:'', W:'' } ) {
            var disabled = state.get(d, "?")!="?" || countMe>0;
            var elemEn = document.getElementById("enCompass"+d);
            var elemDis = document.getElementById("disCompass"+d);
            if(disabled) {
                elemDis.style.display = "inline";
                elemEn.style.display = "none";
            } else {
                elemEn.style.display = "inline";
                elemDis.style.display = "none";
            }
        }
        if(gadgets) gadgets.window.adjustHeight();
    }

    function init() {
      if (wave && wave.isInWaveContainer()) {
        wave.setStateCallback(stateUpdated);
        if(gadgets) gadgets.window.setTitle('Bridgy');
      }
    }
    if(gadgets) gadgets.util.registerOnLoadHandler(init);

    function compass(d) {
        var me = wave.getViewer().getId();
        wave.getState().submitValue(d, me);
    }

    </script>

<div id=divAll>
  <table><tr><td width=100%%><span id=spnBridgy onclick='showVersion()'>Bridgy</span><span id=spnVersion onclick='hideVersion()'>%(version)s</span> <span id=spnTitle></span></td><td> <span class='btn en' id=btnClear onclick='clearBridgy()'>clear</span></td></tr></table>
  <div id=divGameSelect>
    %(contentDivGameSelect)s
  </div>
  <div id=divGame>
    %(contentDivGame)s
  </div>
<div>

""") % {
    'C':'''<span style=color:#00c;>&clubs;</span>''',
    'D':'''<span style=color:#f80;>&diams;</span>''',
    'H':'''<span style=color:#f40;>&hearts;</span>''',
    'S':'''<span style=color:#666;>&spades;</span>''',
    'contentDivGameSelect' : contentDivGameSelect,
    'contentDivGame' : contentDivGame,
    'css' : CSS,
    'version': __version__ + "<br/>" + __author__,
    }

def do_google_wave(form):
    global DIV
    print (
"""Content-Type: text/xml

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Bridgy" height="200">
  <Require feature="wave" />
  <Require feature="dynamic-height" />
  <Require feature="settitle"/>
</ModulePrefs>
<Content type="html">
<![CDATA[""" + DIV + """
  ]]>
  </Content>
</Module>
""")
    return

def do_cgi(form):
    global DIV
    print "Content-Type: text/html"
    print
    print "<html><head>"
    print "  <script type='text/javascript'>"
    print "  var gadgets = false;"
    print "  var mock_viewer = {"
    print "    getId : function() { return 'towi@geocities.com'; }, "
    print "  };"
    print "  var data = {};"
    print "  var mock_state = {"
    print "    get : function(k,dfl) { var v = data[k]; return v==null ? dfl : v; }, "
    print "    submitDelta : function(ds) { for(var k in ds) data[k]=ds[k]; stateUpdated(); }, "
    print "    submitValue : function(k,v) { data[k]=v; stateUpdated(); }, "
    print "  };"
    print "  var wave = {"
    print "    getViewer : function() { return mock_viewer; }, "
    print "    getState  : function() { return mock_state; }, "
    print "  };"
    print "  </script>"
    print "</head>"
    print "<body onLoad='stateUpdated()'>"
    print "  <div style='border:10px solid blue; width:300px; height:200px'>"
    print DIV
    print "  </div>"
    print "</body></html>"


form = cgi.FieldStorage()
if "test" in form:
    do_cgi(form)
else:
    do_google_wave(form)
